local CMD = require "game_proto"
local skynet = require "skynet"

local MJCONST =  require "const"
local TABLECONST = MJCONST.TABLECONST
local CHAIRCONST = MJCONST.CHAIRCONST
local PAICONST = MJCONST.PAICONST
local WIKTYPE = MJCONST.WIKTYPE
local HUTYPE = MJCONST.HUTYPE

local TableConfig = {}


local FANWAIFAN = {QINGYISE=0x0001,HAIDIHU=0x0002,HAIDIPAO=0x0004,GANGHUA=0x0008,GANGPAO=0x0010,QUANQIUREN=0x0020,QIANGGANGHU=0x0040,TIANHU=0x0080,DIHU=0x0100,MENQINIG=0x0200,QUANQIURENDIANPAO=0x0400,SHISANYAO=0x0800,ZIYISE=0x1000}


ChairAction = {}

local UserActions = {}

BufTool = {}
function BufTool.WriteOffset(len)
    local str = ''
    for i = 1, len do
        local usrAct = string.char(0) 
        str = str..usrAct
    end
    return str
end

local MainCmdId = CMD.Main_ClientAndGameSvr_TableModle

function UserActions:New(obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self
	return obj
end

function UserActions:Reset()
	for i = 1, #self do
		self[i] = nil
	end
end

function UserActions:GetPackString()
    local buf = ''
	local num = #self
    buf = buf..string.pack('B', num)
	local hasHU = false
	for i = 1, num do
		local act = self[i]
        local oneTypeNum = 0
        if act.Type == WIKTYPE.WIK_LINE then 
            oneTypeNum = #act.tabChi    --多少种吃法
        end
		buf = buf..string.pack('BBB', act.Type, act.CardData, oneTypeNum)
        for i = 1, oneTypeNum do 
            buf = buf..string.pack('BB', act.tabChi[i].b, act.tabChi[i].a)   --chi
        end
        buf = buf..BufTool.WriteOffset((3 - oneTypeNum) * 2)   --chi
        buf = buf..BufTool.WriteOffset(32)  
		if act.Type == WIKTYPE.WIK_HU then hasHU = true end
	end
    buf = buf..BufTool.WriteOffset((CHAIRCONST.MAX_ACTION_SELECTTION - num) * 41)    --41是OneActionData的大小
    buf = buf..BufTool.WriteOffset(32)  
    return buf
end

function ChairAction:New(obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self
	return obj
end

function ChairAction:ClearChair()
    self.tabCbCardIndex = {}
    self.tabCbOutCard = {}
    self.tabWeaveItem = {}
    self.tabUserAction = {}
    self.tabTingCardData={}
    self.tabToDo = {}
    self.HasDispatchXiPai = false
    self.DoneHu = false
    self.OutCardCount = 0
    self.tabLiaoLong = {}
    self.tabXiPai = {}
    self.tabHuInfo = {}
    UserActions:Reset()
    self.GameScoreJu = 0
    self.DoneBaoTing = -1
    self.OperateBit = 0
    self.ResultMsg = ''
    self.GangScore = 0
    self:ResetLou()
end

function ChairAction:MakeReadyChair(tabFrame) 
    self:ClearChair()
    self:Init()
    self.tabFrame = tabFrame
    TableConfig = self.tabFrame.TableConfig
end

function ChairAction:Quit()
    self:ClearChair()
    self.addr = nil
end

function ChairAction:RegisterFun()
    self.DoMsgList = {}
    self.DoMsgList[WIKTYPE.WIK_LINE]    =  {Type = WIKTYPE.WIK_LINE,    Func = self.DoChi}
    self.DoMsgList[WIKTYPE.WIK_PENG]    =  {Type = WIKTYPE.WIK_PENG,    Func = self.DoPeng}
    self.DoMsgList[WIKTYPE.WIK_ANGANG]  =  {Type = WIKTYPE.WIK_ANGANG,  Func = self.DoAnGang}
    self.DoMsgList[WIKTYPE.WIK_JIEGANG] =  {Type = WIKTYPE.WIK_JIEGANG, Func = self.DoJieGang}
    self.DoMsgList[WIKTYPE.WIK_JIAGANG] =  {Type = WIKTYPE.WIK_JIAGANG, Func = self.DoJiaGang}
    --self.DoMsgList[WIKTYPE.WIK_DU]      =  {Type = WIKTYPE.WIK_JIAGANG, Func = self.DoJiaGang}
    self.DoMsgList[WIKTYPE.WIK_HU]      =  {Type = WIKTYPE.WIK_HU,      Func = self.DoHu}
    
    self.CANCELCMD = {}
    self.CANCELCMD[WIKTYPE.WIK_LINE]    = CMD.Sub_GameSvrToClient_TableModle_UserCancelChiOk
    self.CANCELCMD[WIKTYPE.WIK_PENG]    = CMD.Sub_GameSvrToClient_TableModle_UserCancelPengOk
    self.CANCELCMD[WIKTYPE.WIK_JIEGANG] = CMD.Sub_GameSvrToClient_TableModle_UserCancelPengOk
    self.CANCELCMD[WIKTYPE.WIK_JIAGANG] = CMD.Sub_GameSvrToClient_TableModle_UserCancelJiaGangOk
    self.CANCELCMD[WIKTYPE.WIK_ANGANG]  = CMD.Sub_GameSvrToClient_TableModle_UserCancelAnGangOk
    self.CANCELCMD[WIKTYPE.WIK_HU]      = CMD.Sub_GameSvrToClient_TableModle_UserCancelHu
end

function ChairAction:Init()
    self:RegisterFun()
	for i = 1, PAICONST.MAX_INDEX  do 
		self.tabCbCardIndex[i] = 0
	end
    self.tabUserAction = UserActions:New()
	self.tabCardVal = {}
end

function ChairAction:SendData(msg)
    send_data(self.addr, msg)
end

function ChairAction:SendDataInLua(subId, msg)
    local msgSend = string.pack('>I2>I2', MainCmdId, subId)
    if msg then msgSend = msgSend..msg end
    send_data(self.addr, msgSend)
end

function ChairAction:StartFaPai(wJu)
    local gameStartDataMsg = string.pack("<I2<I2<I2", wJu, self.tabFrame.Banker, self.tabFrame.Banker)
    gameStartDataMsg = gameStartDataMsg..self.tabUserAction:GetPackString()
    gameStartDataMsg = gameStartDataMsg..string.pack('b', 83)
    for i = 1, TABLECONST.NUM_HANDFULL do 
        gameStartDataMsg = gameStartDataMsg..string.pack('b', self.tabCardVal[i] or 0)
    end
    local strLogFapai = 'FaPai is '
    table.sort(self.tabCardVal)
    for i = 1, TABLECONST.NUM_HANDFULL do 
        strLogFapai = strLogFapai..string.format('%0x ', self.tabCardVal[i] or 0)
    end
    skynet.error(strLogFapai)
    self:SendDataInLua(CMD.Sub_GameSvrToClient_TableModle_GameStartData, gameStartDataMsg)
end

function ChairAction:OnDispatchCard(cbCardData, nLeftCardCount, permitOutCard)   --椅子摸牌
    if cbCardData ~= 0 then     
        local ind = MjLogic:ValToIndex(cbCardData)
        self.tabCbCardIndex[ind] = self.tabCbCardIndex[ind] + 1
    end
    if true then 
        self:ResetLou()
        if self.tabFrame.LeftCardCount > 0 then    --摸最后一张牌时不许杠
            self:CanGang(cbCardData, WIKTYPE.WIK_ANGANG)
            self:CanGang(cbCardData, WIKTYPE.WIK_JIAGANG)
            self:CanGang(cbCardData, WIKTYPE.WIK_DU)    --是否可以笃（不要补牌）
        end
        self:CanHu(cbCardData)
        
        -- local str = ''
        -- local standCard = self:GetStandCard() 
		-- for i = 1, TABLECONST.NUM_HANDFULL do   --23个
			-- local val = standCard[i]
            -- str = str..string.format('%0x ', val or 0)
		-- end
        
    end
	
    local dispatchMsg = string.pack("I2B", self.UserChairID, cbCardData)
    dispatchMsg = dispatchMsg..self.tabUserAction:GetPackString()
    dispatchMsg = dispatchMsg..string.pack("I2", nLeftCardCount)
    
    self:SendDataInLua(CMD.Sub_GameSvrToClient_TableModle_DispatchCardToMe, dispatchMsg)
end

function ChairAction:AddHandCard(val)
    local ind = MjLogic:ValToIndex(val)
    self.tabCbCardIndex[ind] = self.tabCbCardIndex[ind] + 1
end

function ChairAction:OnOutCard(cbCardData)        --椅子出牌
	local ind = MjLogic:ValToIndex(cbCardData)
	self.tabCbCardIndex[ind] = self.tabCbCardIndex[ind] - 1
	self.tabCbOutCard[#self.tabCbOutCard + 1] = cbCardData
    self.OutCardCount = self.OutCardCount + 1
end


function ChairAction:OthersCardToMe(wOtherUserId, nLeftCardCount)
	local msg = string.pack('>I2>I2', MainCmdId, CMD.Sub_GameSvrToClient_TableModle_DispatchCardToOther)
    msg = msg..string.pack('I2B', wOtherUserId, nLeftCardCount)
	self:SendData(msg)
end

function ChairAction:UpdataTingData()
	self.tabTingCardData = MjLogic:IsTing(self.tabCbCardIndex, self.tabWeaveItem)
	local tingLen = #self.tabTingCardData.val
    local msg = string.pack('>I2>I2<B', MainCmdId, CMD.Sub_GameSvrToClient_TableModle_UpdateTingCardData, tingLen)
	if tingLen > 0 then
		for i = 1, #self.tabTingCardData.val do
            local v = string.pack('B', self.tabTingCardData.val[i])
            msg = msg..v
		end
        for i = 1, CHAIRCONST.MAX_TINGNUM - tingLen do 
            local v = string.pack('B', 0)
            msg = msg..v
        end
		self:SendData(msg)
	else
        for i = 1, CHAIRCONST.MAX_TINGNUM + 1 do 
            local v = string.pack('B', 0)
            msg = msg..v
        end    
		self:SendData(msg)
	end
end

function ChairAction:IsLouPeng(getData)
    if self.LouPeng then 
        if self.LouPeng[getData] then skynet.error(' Chair Id '..self.UserChairID..' LouPeng :'..getData) end
        return self.LouPeng[getData]
    end
    return false
end

function ChairAction:IsLouHu()
    if self.LouHu then skynet.error(' Chair Id '..self.UserChairID..' LouHu') end
	return self.LouHu or false
end

function ChairAction:CheckHu(getData)
	local cardIndex = DeepCopy(self.tabCbCardIndex)
	local bZiMo = true
	if MjLogic:GetHandCardNum(self.tabCbCardIndex) % 3 == 1 then 
		local index = MjLogic:ValToIndex(getData)
		cardIndex[index] = cardIndex[index] + 1
		bZiMo = false
	end 
	if #self.tabTingCardData == 0 or #self.tabTingCardData.val == 0 then return false end
	local bHu = false
	local type = 0
	for i = 1, #self.tabTingCardData.val do
		if self.tabTingCardData.val[i] == getData then
			bHu = true 
			type = self.tabTingCardData.type[i]
			break
		end 
	end 
	if not bHu then return false
	else return true, type end
end

function ChairAction:CanHu(cbCardData, provider)
    local bHu, type = self:CheckHu(cbCardData)
	if bHu then 
        if self.tabFrame.PingHuZiMo and type == HUTYPE.HT_PINGHU and provider then return false end   --平胡需自摸
		local tabAction = {}
		tabAction.Type = WIKTYPE.WIK_HU
		tabAction.CardData = cbCardData
        tabAction.Provider = provider
		self.tabUserAction[#self.tabUserAction + 1] = tabAction
		return true
	end
	return false
end

function ChairAction:CanGang(getData, type, Provider)       --加了该张牌,可能有多个暗杠的牌
	if type == WIKTYPE.WIK_ANGANG then 
		local gang = {}
		for i = 1, PAICONST.MAX_INDEX do 
			if self.tabCbCardIndex[i] > 3 then 
				local val = MjLogic:IndexToVal(i)
				local tabAction = {}
				tabAction.CardData = val
				tabAction.Type = WIKTYPE.WIK_ANGANG
				self.tabUserAction[#self.tabUserAction + 1] = tabAction
				gang[#gang + 1] = val
			end
		end
		return #gang > 0, gang
	elseif type == WIKTYPE.WIK_JIEGANG and getData > 0 then
		local index = MjLogic:ValToIndex(getData)
		local num = self.tabCbCardIndex[index]
		local tabAction = {}
		tabAction.Type = type
		tabAction.CardData = getData
        tabAction.Provider = Provider
		local bJieGang = false
		if num == 3 then 
			self.tabUserAction[#self.tabUserAction + 1] = tabAction
			bJieGang = true
		end
		return bJieGang
    elseif type == WIKTYPE.WIK_JIAGANG then 
        for i = 1, #self.tabWeaveItem do
            local bFind = false
            for j = 1, PAICONST.MAX_INDEX do 
                if self.tabCbCardIndex[j] == 1 then 
                    local val = MjLogic:IndexToVal(j)                  
                    local weaveItem = self.tabWeaveItem[i]
                    if weaveItem.Kind == WIKTYPE.WIK_PENG and weaveItem.CenterCard == val then 
                        local tabAction = {}
                        tabAction.Type = type
                        tabAction.CardData = val
                        tabAction.Provider = weaveItem.Provider     --加杠的提供者是碰的那个
                        self.tabUserAction[#self.tabUserAction + 1] = tabAction
                        bFind = true
                        break
                    end
                end
            end
            if bFind then break end
        end
      
    elseif type == WIKTYPE.WIK_DU then
        for i = 1, PAICONST.MAX_INDEX do 
			if self.tabCbCardIndex[i] == 3 then 
				local val = MjLogic:IndexToVal(i)
                local tabAction = {}
                tabAction.Type = WIKTYPE.WIK_JIAGANG   --还是按加杠算
                tabAction.CardData = val
                if self.tabFrame.tabJiang[1] == val or self.tabFrame.tabJiang[2] == val then 
                    self.tabUserAction[#self.tabUserAction + 1] = tabAction
                    print('************du getData is ', val)
                end
                break
            end
		end
	end  
end

function ChairAction:CanPeng(getData, provider)       --还没有加该张牌
    --if self:IsLouPeng(getData) then return false end         --漏碰
	local index = MjLogic:ValToIndex(getData)
	local num = self.tabCbCardIndex[index]
	local tabAction = {}
	tabAction.CardData = getData
    tabAction.Provider = provider
	if num >= 2 then 
		tabAction.Type = WIKTYPE.WIK_PENG
		self.tabUserAction[#self.tabUserAction + 1] = tabAction
		return true
	end
	return false
end

function ChairAction:CanChi(getData, provider)       --还没有加该张牌
    if not self.tabFrame.CanChi then return false end
    if getData&0xF0 == 0x30 then return false end    --风
	local index = MjLogic:ValToIndex(getData)
    local tabChi = {}
    if (getData&0x0F > 2) and self.tabCbCardIndex[index - 2] > 0 and self.tabCbCardIndex[index - 1] > 0 then
       local chi = {b = getData - 2, a = getData - 1}
       tabChi[#tabChi + 1] = chi
    end
    
    if (getData&0x0F > 1 and getData&0x0F < 9) and self.tabCbCardIndex[index - 1] > 0 and self.tabCbCardIndex[index + 1] > 0 then
       local chi = {b = getData - 1, a = getData + 1}
       tabChi[#tabChi + 1] = chi
    end
    
    if (getData&0x0F < 8) and self.tabCbCardIndex[index + 1] > 0 and self.tabCbCardIndex[index + 2] > 0 then
        local chi = {b = getData + 1, a = getData + 2}
        tabChi[#tabChi + 1] = chi
    end
    
	if #tabChi > 0 then 
        local tabAction = {}
        tabAction.CardData = getData
        tabAction.Provider = provider
		tabAction.Type = WIKTYPE.WIK_LINE
        tabAction.tabChi = tabChi
		self.tabUserAction[#self.tabUserAction + 1] = tabAction
		return true
	end
	return false
end

function ChairAction:SendOperateHint(empty)	
    if #self.tabUserAction > 0 or empty then     
        local msg = self.tabUserAction:GetPackString()
        local protol = CMD.Sub_GameSvrToClient_TableModle_CanPengOrJieGang
        if hasHU then protol = CMD.Sub_GameSvrToClient_TableModle_CanDianPaoHu end
        self:SendDataInLua(protol, msg)
    end
end

function ChairAction:DoHu(getCardData)
    local provider
    local bHu, huType = self:CheckHu(getCardData)
    local tabAction = self:CouldOperate(WIKTYPE.WIK_HU, getCardData)
    if bHu and tabAction then
        provider = tabAction.Provider
        self.tabUserAction:Reset()
    end
    if not bHu then return nil end
    local bQiangGangHu = false
    if (self.OperateBit & WIKTYPE.WIK_QGHU) ~= 0 then bQiangGangHu = true end
    self.OperateBit = 0
	return {HuType = huType, Provider = provider, QGHu = bQiangGangHu}
end

function ChairAction:DoChiPengGangActReq(act, centerCard, cardBef, cardAft)   --吃碰杠请求
    print('$$$$$$$$$$$$DoChiPengGangActReq id is ', self.UserChairID)
    local tabAction = self:CouldOperate(act.Type, centerCard)
	if tabAction then 
        self.tabUserAction:Reset()
        if self.tabFrame:WaitForOtherActs(self, act.Type, centerCard, cardBef, cardAft, tabAction.Provider) then return false end
        local bDone = act.Func(self, tabAction, centerCard, cardBef, cardAft)
		return bDone and tabAction.Provider   --true and 1 == 1  会返回Provider，其中在DoAnGang中会设置其Provider
	else print('***********ChairAction:DoChiPengGangActReq could not') return nil end
end

function ChairAction:DoDelayAction(type, tabCardData, provider)
    if type ~= WIKTYPE.WIK_HU then 
        self:DoAction(type, tabCardData, provider)
        self.tabFrame:DoActionCmd(type, self, provider, tabCardData[1], tabCardData[2] or 0, tabCardData[3] or 0)
        self.tabFrame:SetNextUser()
        if type == WIKTYPE.WIK_JIAGANG then 
            self.tabFrame:DispatchCard(self, type)
        end
    else 
        local huInfo = self:DoHu(tabCardData[1])
        if huInfo then
            self.tabFrame:DoHuCmd(self,tabCardData[1], huInfo)
        end
    end
end

function ChairAction:DoPeng(tabAction, centerCard)
	return self:DoAction(WIKTYPE.WIK_PENG, {centerCard}, tabAction.Provider)
end

function ChairAction:DoChi(tabAction, centerCard, cardBef, cardAft)
    if self.tabFrame:DoOthersHigherAct(self, WIKTYPE.WIK_LINE) then 
        if self.tabUserAction then 
            self.tabUserAction:Reset() 
        end
        self.tabToDo = nil
        return false
    end
    
    local index1 = MjLogic:ValToIndex(cardBef)
    local index2 = MjLogic:ValToIndex(cardAft)
    self.tabCbCardIndex[index1] = self.tabCbCardIndex[index1] - 1
    self.tabCbCardIndex[index2] = self.tabCbCardIndex[index2] - 1
	self:ResetLou()
	local weaveItem = {}
	weaveItem.CenterCard = centerCard
    weaveItem.Bef = cardBef
    weaveItem.Aft = cardAft
	weaveItem.Provider = tabAction.Provider;
	weaveItem.Kind = WIKTYPE.WIK_LINE
	table.insert(self.tabWeaveItem, weaveItem) 
    
	if self.tabUserAction then 
		self.tabUserAction:Reset() 
	end
    for chair in self.tabFrame:ChairIterator() do 
       chair.tabToDo = nil     --动作都执行了,每个延迟的就清空
    end
    return true
end

function ChairAction:DoJieGang(tabAction, centerCard)
	self:DoAction(WIKTYPE.WIK_JIEGANG, {centerCard}, tabAction.Provider)
    self:UpdataTingData()
    self.LianGang = 1
    return true
end

function ChairAction:DoJiaGang(tabAction, centerCard)
    function DoRealJiaGang(tabAction, centerCard)
        self:DoAction(WIKTYPE.WIK_JIAGANG, {centerCard}, tabAction.Provider)
        self:UpdataTingData()
        self.LianGang = (self.LianGang or 0) + 1 
        return true
    end
    
    return DoRealJiaGang(tabAction, centerCard)
end

function ChairAction:DoAnGang(tabAction, centerCard)
    tabAction.Provider = self.UserChairID
	self:DoAction(WIKTYPE.WIK_ANGANG, {centerCard})
    self:UpdataTingData()
    self.LianGang = (self.LianGang or 0) + 1
    return true
end

function ChairAction:DoAction(type, cardData, provider)   --上层(例如DoAnGang)执行之后再执行这个
    local centerCard = cardData[1]
	local valIndex = MjLogic:ValToIndex(centerCard)
	local numToMinus = 0
    local scoreType 
	if type == WIKTYPE.WIK_PENG then
        numToMinus = 2 
        scoreType = 'peng'
	elseif type == WIKTYPE.WIK_JIEGANG then
        numToMinus = 3 
        scoreType = 'minggang'
	elseif type == WIKTYPE.WIK_JIAGANG then 
        numToMinus = 1
        scoreType = 'jiagang'
	elseif type == WIKTYPE.WIK_ANGANG then 
        numToMinus = 4 
        scoreType = 'angang'
	else 
        numToMinus = 0 
    end
	self.tabCbCardIndex[valIndex] = self.tabCbCardIndex[valIndex] - numToMinus
	self:ResetLou()
	local weaveItem = {}
	weaveItem.CenterCard = centerCard
	weaveItem.Provider = provider;
	weaveItem.Kind = type
    weaveItem.ScoreKind = scoreType
    if type == WIKTYPE.WIK_JIAGANG then    --如果是加杠，那么就替换表里面的碰
        for k, v in pairs(self.tabWeaveItem) do
            if v.CenterCard == centerCard then 
                self.tabWeaveItem[k] = weaveItem
                break
            end
        end
    else
        table.insert(self.tabWeaveItem, weaveItem)
    end
    
    if self.tabUserAction then 
		self.tabUserAction:Reset() 
	end
    for chair in self.tabFrame:ChairIterator() do 
       chair.tabToDo = nil     --动作都执行了,每个延迟的就清空
    end
    return true    
end

function ChairAction:ResetLou()
    self.LouHu = false
    self.LouPeng = {}
end

function ChairAction:CouldOperate(type, centerCard)
    local useAct = nil
	for i = 1, #self.tabUserAction do
		if self.tabUserAction[i].Type == type and self.tabUserAction[i].CardData == centerCard then
            useAct = self.tabUserAction[i]
			break
		end
	end
	return useAct
end

function ChairAction:CancelActionReq(type)     --有可能已经取消,要防止重复
    local bOk, centerCard = self:CancelAction(type)
	if bOk then
        self:SendDataInLua(self.CANCELCMD[type])
        if type == WIKTYPE.WIK_HU then         --漏胡
            self.LouHu = true
        elseif type == WIKTYPE.WIK_PENG then
            self.LouPeng = self.LouPeng or {}
            if centerCard then self.LouPeng[centerCard] = true end
        end
        skynet.error('Chair Id '..self.UserChairID..' Cancel type is'..type..' Card is '..centerCard)
		return true
	end
	return false
end

function ChairAction:CancelAction(type)
	local bHas = false
    local centerCard
	for i = 1, #self.tabUserAction do
		if self.tabUserAction[i].Type == type then
			bHas = true
            centerCard = self.tabUserAction[i].CardData
			self.tabUserAction:Reset()
			break
		end
	end
	return bHas, centerCard
end

function ChairAction:OnLiuJu()
	
end

function ChairAction:ConcludeGame(huData)
	-- self.standCard = {}     --站立的牌
	-- local nStand = 0
	-- for i = 1, #self.tabCbCardIndex do 
		-- local indexNum = self.tabCbCardIndex[i]
		-- for j = 1, indexNum do
			-- nStand = nStand + 1
			-- self.standCard[nStand] = MjLogic:IndexToVal(i) 	
		-- end
	-- end
	
    --if huData.LiuJu then self.ResultMsg = "流局" end
    
    if self.ResultMsg == '' then 
        if self.GangScore ~= 0 then 
            self.ResultMsg = string.format(' 杠分%d', self.GangScore)
        end
    end
end

function ChairAction:IsFanWaiFan(name)
    function IsTianHu()
        if self.tabFrame.Banker == self.UserChairID and self.OutCardCount == 0 then return true
        else return false 
        end
    end
    function IsDiHu()
        for chair in self.tabFrame:ChairIterator() do
            if chair.UserChairID == self.tabFrame.Banker then 
                if #chair.tabCbOutCard ~= 1 then return false end
            else
                if #chair.tabCbOutCard ~= 0 then return false end
            end
        end
        return true
    end
   
    function IsQiangGangHu()
        return self.tabHuInfo.QGHu
    end
    
    function IsHaiDiLao() return self.tabFrame.LeftCardCount == 0 end
    function IsHaiDiPao() end
    
    function IsGang(wik)
        local tab = {[WIKTYPE.WIK_JIAGANG]=true, [WIKTYPE.WIK_ANGANG]=true, [WIKTYPE.WIK_JIEGANG]=true}
        return tab[wik]
    end
        
    function IsGangHu()   --1为杠花，2为杠炮
        if self.tabHuInfo and self.tabHuInfo.Hu then    --胡了
            local chGang = self
            if self.tabHuInfo.ZiMo == false then
                chGang = self.tabFrame:UserIdToChair(self.tabHuInfo.ProviderId)
            end
            for k, v in pairs(chGang.tabWeaveItem) do       --手上有杠的牌
                if IsGang(v.Kind) then    --有杠
                    if v.dispatchCardInfo then
                        print(string.format('*********** getCard is %0x,%0x, leftCard is %d,%d OutCardCount is %d,%d', v.dispatchCardInfo.getCard, self.tabHuInfo.CardData, v.dispatchCardInfo.leftCard, self.tabFrame.LeftCardCount, v.dispatchCardInfo.outCardCount,chGang.OutCardCount))
                    end
                    if v.dispatchCardInfo and v.dispatchCardInfo.leftCard == self.tabFrame.LeftCardCount then 
                        if self.tabHuInfo.ZiMo then      --自摸时出的牌数和杠花时一样
                            if v.dispatchCardInfo.outCardCount == chGang.OutCardCount then return 1 end
                        else                             --点炮时出的牌数比杠花多一张
                            if (v.dispatchCardInfo.outCardCount + 1) == chGang.OutCardCount then return 2 end
                        end
                       break
                    end
                end
            end
        end
        return 0
    end
    
    function IsGangHua() return 1 == IsGangHu() end
    function IsGangPao() return 2 == IsGangHu() end
    function IsQingYiSe() 
        return MjLogic:IsQingYiSe(self.tabCbCardIndex, self.tabWeaveItem)
    end
    function IsPengPengHu()
        return self.tabHuInfo.HuType == HUTYPE.HT_PENGPENGHU
    end
    
    local tabFan = {
        ['tianhu']      = IsTianHu,
        ['dihu']        = IsDiHu,
        ['ganghua']     = IsGangHua,
        ['gangpao']     = IsGangPao,
        ['qingyise']    = IsQingYiSe,
        ['pengpenghu']  = IsPengPengHu,
        ['qiangganghu'] = IsQiangGangHu
    }
    if tabFan[name] then return tabFan[name]() end
    return false
end

function ChairAction:GetFanWaiFan()
    local fan = 0
 
    if self:IsFanWaiFan('tianhu') then fan=fan|FANWAIFAN.TIANHU end
    if self:IsFanWaiFan('dihu') then fan=fan|FANWAIFAN.DIHU end
    if self:IsFanWaiFan('qingyise') then fan=fan|FANWAIFAN.QINGYISE end
    if self:IsFanWaiFan('ganghua') then fan=fan|FANWAIFAN.GANGHUA end
    if self:IsFanWaiFan('gangpao') then fan=fan|FANWAIFAN.GANGPAO end

    return fan
end

function ChairAction:GetStandCard()
    local standCard = {}
    local nStand = 0
    for i = 1, #self.tabCbCardIndex do 
        local num = self.tabCbCardIndex[i]
        for j = 1, num do
            nStand = nStand + 1
            standCard[nStand] = MjLogic:IndexToVal(i) 	
        end
    end
    for i = 1, #standCard do
        if self.tabHuInfo.ZiMo and standCard[i] == self.tabHuInfo.CardData then   --自摸的时候要去掉胡的这个牌
            table.remove(standCard, i)
            break
        end
    end
    self.standCard = standCard
    return standCard
end

function ChairAction:CalScore()
    function IsGang(wik)
        local tab = {[WIKTYPE.WIK_JIAGANG]=true, [WIKTYPE.WIK_ANGANG]=true, [WIKTYPE.WIK_JIEGANG]=true}
        return tab[wik]
    end

    function GetGuiNum()
        local gui = 0
        for k, v in pairs(self.tabWeaveItem) do 
            if IsGang(v.Kind) then return 0 end  --有杠就不算归
        end
        if self.DoneHu then 
            for i = 1, #self.tabCbCardIndex do      --手上有4个一样的牌
                local num = self.tabCbCardIndex[i]
                if num == 4 then gui = gui + 1 end
            end
            
            for k, v in pairs(self.tabWeaveItem) do       --手上有碰的牌
                if v.Kind == WIKTYPE.WIK_PENG then 
                    local ind = MjLogic:ValToIndex(v.CenterCard)
                    if self.tabCbCardIndex[ind] == 1 then gui = gui + 1 end
                end
            end
        else      
            for i = 1, #self.tabTingCardData.val do  --听了
                local val = self.tabTingCardData.val[i]
                for k, v in pairs(self.tabWeaveItem) do 
                    if v.CenterCard == val then gui = gui + 1 break end
                end
            end
        end
        return gui
    end
    
    function GetGangNum()
        local num = 0
        for k, v in pairs(self.tabWeaveItem) do
            if IsGang(v.Kind) then num = num + 1 end
        end
        return num
    end
    
    function IsQiDui()
        if self.tabHuInfo.HuType == HUTYPE.HT_QIXIAODUI then return 0
        elseif self.tabHuInfo.HuType == HUTYPE.HT_QIDADUI then return 1
        elseif self.tabHuInfo.HuType == HUTYPE.HT_HAOQI then return 2
        elseif self.tabHuInfo.HuType == HUTYPE.HT_CHAOHAOQI then return 3
        else return -1 end
    end
    
    function IsKaErTiao()
        if self:IsFanWaiFan('tianhu') then return false end
        if self.tabHuInfo.CardData ~= 0x12 then return false end
        local tempIndex = DeepCopy(self.tabCbCardIndex)
        if MjLogic:GetHandCardNum(self.tabCbCardIndex) % 3 == 1 then 
            local ind = MjLogic:ValToIndex(self.tabHuInfo.CardData)
            tempIndex[ind] = tempIndex[ind] + 1            
        end
        local _, tabTiao, _, _ = MjLogic:ParsePaiToWTTZ(tempIndex)
        local tabKsq = {ksq = {k = 0,s = 0,q = 0}}
        MjLogic:ProcessOneColor(tabTiao, true, tabKsq)
        for _, v in pairs(tabKsq.ksq.sv or {}) do
            if v == 0x12 then return true end
        end
        return false
    end
    
    local tabBeiShu = {
        {fanName = 'tianhu',      bei = 2,  tip='天胡'},
        {fanName = 'dihu',        bei = 1,  tip='地胡'},
        {fanName = 'ganghua',     bei = 1,  tip='杠上花'},
        {fanName = 'gangpao',     bei = 1,  tip='杠上炮'},
        {fanName = 'qiangganghu', bei = 1,  tip='抢杠胡'},
        
        --{fanName = 'pengpenghu',  bei = 2,  tip='大对子'},
        --{fn = (function() return self.tabHuInfo.ZiMo end),  bei = 1,  tip='自摸'}, 
        {fn = (function() return self.DoneBaoTing > 0 end), bei = 1,  tip='报叫'},
        {fn = IsKaErTiao, bei = 1,  tip='卡二条'},
    }
    
    function IsTuiDaoHu()
        if self.tabHuInfo.HuType == HUTYPE.HT_PINGHU
           and not self:IsFanWaiFan('qingyise') then
           return true
        end   
        return false
    end
   
    local fanShu = 0
    local tips = ''
    local strDes = ''
    local qingyise,nDui = false, -1
    for _, v in pairs(tabBeiShu) do 
        if v.fanName and self:IsFanWaiFan(v.fanName) then
            tips = tips..' '..(v.tip or '' )
            fanShu = fanShu + v.bei
            strDes = strDes..v.tip..' bei:'..v.bei
        end
        if v.fn and v.fn() then
            fanShu = fanShu + v.bei
            tips = tips..' '..(v.tip or '' )
            strDes = strDes..v.tip..' bei:'..v.bei
        end
    end
    local qingyise,nDui = self:IsFanWaiFan('qingyise'), IsQiDui()
    if qingyise then 
        local pph = self:IsFanWaiFan('pengpenghu')
        if pph then 
            tips = tips..' '..'清对'
            fanShu = fanShu + 4
            strDes = strDes..'清对'..' bei:4'
        else
            if nDui >= 0 then    --清一色对子
                local tab = {
                    [0] = {bei = 4, tip = '清七对'},
                    [1] = {bei = 5, tip = '清龙七对'},
                    [2] = {bei = 6, tip = '清双龙七对'},
                    [3] = {bei = 7, tip = '清三龙七对'},
                } 
                fanShu = fanShu + tab[nDui].bei
                tips = tips..' '..(tab[nDui].tip or '' )
                strDes = strDes..tab[nDui].tip..' bei:'..tab[nDui].bei
            else
                fanShu = fanShu + 2
                tips = tips..' '..'清一色'
                strDes = strDes..'清一色'..' bei:2'
            end
        end
    else                     --非清一色对子
        if nDui >=0  then
            local tab = {
                [0] = {bei = 2, tip = '暗七对'},
                [1] = {bei = 3, tip = '龙七对'},
                [2] = {bei = 4, tip = '双龙七对'},
                [3] = {bei = 5, tip = '三龙七对'},
            }
            fanShu = fanShu + tab[nDui].bei
            tips = tips..' '..(tab[nDui].tip or '' )
            strDes = strDes..tab[nDui].tip..' bei:'..tab[nDui].bei
        end
        
        if self:IsFanWaiFan('pengpenghu') then 
            tips = tips..' '..'大对子'
            fanShu = fanShu + 2
            strDes = strDes..'大对子'..' bei:2'
        end
    end
    local nGang, nGui = GetGangNum(), GetGuiNum()
    fanShu = fanShu + nGang   --杠的数量
    fanShu = fanShu + nGui    --归
    if nGang > 0 then tips = tips..string.format(' %d杠', nGang) end
    if nGui > 0 then tips = tips..string.format(' %d归', nGui) end
    strDes = strDes..string.format('gang:%d, gui:%d', nGang, nGui)
    print('############', strDes)
    if self.GangScore ~= 0 then 
        tips = tips..string.format(' 杠分%d', self.GangScore)
    end
    self.ResultMsg = tips
    
    if self.tabHuInfo.ZiMo and TableConfig.ZmJiaFan then 
        fanShu = fanShu + 1
    end
    
    local fen = 0
    if TableConfig.JiPing then    --极品
        if fanShu > 4 then 
            fen = 16 + (fanShu - 4) * 2
        else fen = 1 << fanShu end
    else   --超过上限
        if fanShu > TableConfig.FanCeil then fanShu = TableConfig.FanCeil end
        fen = 1 << fanShu
    end
    
    if self.tabHuInfo.ZiMo and not TableConfig.ZmJiaFan then   --自摸加一分
        fen = fen + 1 
    end
    return fen, fanShu

end

function ChairAction:SendMeOfflineBackData(index, wUserChairId)
    local bufData = ''
	if index == 'standCard' then
        local str = ''
        local standCard = self:GetStandCard()
		for i = 1, TABLECONST.NUM_HANDFULL do   --14个
			local val = standCard[i]
            bufData = bufData..string.pack('B', val or 0)
            str = str..string.format('%0x ', val or 0)
		end
        
	elseif index == 'weaveItem' then 
		local totalW = 0
        for i = 1, TABLECONST.MAXWEAVCOUNT do   
            local weave = self.tabWeaveItem[i]
            if weave then 
                totalW = totalW + 1
                bufData = bufData..string.pack('BBI2BB', weave.Kind, weave.CenterCard, weave.Provider or 255, weave.Bef or 0, weave.Aft or 0)        
            else 
                bufData = bufData..BufTool.WriteOffset(6)
            end
		end
        
	elseif index == 'outCard' then 
        if not self.tabCbOutCard then 
            bufData = bufData..BufTool.WriteOffset(TABLECONST.MAXOUTCARDCOUNT)
        else 
            for i = 1, TABLECONST.MAXOUTCARDCOUNT do
                bufData = bufData..string.pack('B', self.tabCbOutCard[i] or 0)
            end
        end

	elseif index == 'tingData' then
        if not self.tabTingCardData or not self.tabTingCardData.val then 
            bufData = bufData..BufTool.WriteOffset(TABLECONST.MAX_TING)
        else
            for i = 1, TABLECONST.MAX_TING do                 
                local vt = self.tabTingCardData.val[i]
                bufData = bufData..string.pack('B', vt or 0)
            end
        end	
	end
    return bufData
end
